[inject templates/en.xd]
[gen-title Nim doesn't get in the way]
[p One of the main reasons I like the [link Nim programming language; https://nim-lang.org] is that it doesn't make easy things unnecessarily difficult. Let me show a few examples.]
[section Reading a file;
  [p A common thing one may want to do in programming is to read a file into a string. In C, one could do that like this ([link source; https://stackoverflow.com/questions/174531/how-to-read-the-content-of-a-file-to-a-string-in-c]):]
  [code-block c; [raw<
    FILE *file = fopen("file.txt", "r");
    fseek(file, 0, SEEK_END);
    int length = ftell(file);
    fseek(file, 0, SEEK_SET);
    char *content = malloc(length + 1);
    fread(content, 1, length, file);
    fclose(file);
  ]]
  [p Wow. So much ceremony for such a simple and common task. How about in Python, which is known for being expressive?]
  [code-block python; [raw<
    with open("file.txt") as file:
      content = file.read()
  ]]
  [p Much simpler. But still [---] why not abstract this process into a single function? This is how Nim does it:]
  [code-block nim; let content = readFile("file.txt")]
  [p You might object that the C approach is better because it allows more precise control [---] for example, you can read only a part of a large file without having to waste time. However, Nim doesn't take that away from you [---] if you need fine-grained operations like [code open] and [code seek], they're still available. And it's not just about reading files [---] the concept of abstracting away the most common operations while leaving lower-level constructs for less common operations is idiomatic for Nim.]
]
[section Factorial;
  [p For another example, let's define a function that calculates the factorial of a given number. (In case you don't know, the [term factorial] of a number [<var> n] is the product of all numbers from 1 to [<var> n] inclusive.) Many languages have a factorial function in their standard library, but let's pretend for a moment that they don't just to showcase a few useful features. Let's start with C:]
  [code-block c; [raw<
    int factorial(int n) {
    	int result = 1;
    	for (int i = 1; i <= n; ++i) {
    		result *= i;
    	}
    	return result;
    }
  ]]
  [p Yuck. It's the 21[<sup> st] century and I still have to explain to my computer how to iterate over a range of numbers? Let's turn to Python:]
  [code-block python; [raw<
    def factorial(n: int) -> int:
        result = 1
        for i in range(1, n + 1):
            result *= i
        return result
  ]]
  [p This looks better, but what is that [code python; + 1] doing there? The answer is that Python's [code python; range] function doesn't include the upper bound. Don't get me wrong [---] that's [link a good thing; https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html]. However, sometimes an inclusive range is actually needed, and then it's not Python's time to shine.]
  [p By the way, notice that in both C and Python, we're declaring a variable named [code result] at the beginning and then return it at the end. This is actually a very common pattern in programming. And if something is very common, Nim likes to make it as easy as possible.]
  [code-block nim; [raw<
    func factorial(n: int): int =
      result = 1
      for i in 1..n:
        result *= i
  ]]
  [p Notice that the [code nim; result] variable isn't declared anywhere and there is no [code nim; return] statement. This is Nim's cool trick to resolve the situation described above: every function has an implicit [code nim; result] variable that you can assign to and if you don't explicitly [code nim; return] anything, it will be returned at the end. And of course, this feature is totally optional [---] it won't bother you when you don't need it.]
  [p When it comes to iterating over numbers from 1 to [<var> n], it couldn't be easier. But if we were to need a half-inclusive range (which is needed often), that also wouldn't be a problem [---] just change the [code nim; ..] to [code nim; ..<].]
]
[comments]
